{T}

Nginx 配置文件通用语法与最佳实践

Nginx 配置文件是 Nginx 能力的核心体现。它采用声明式、层次化(多级上下文)、事件驱动的结构,通过配置不同上下文中的指令(directive)来完成反向代理、负载均衡、安全控制、缓存等功能。

配置文件整体结构与上下文层级

典型的主配置文件通常为 /etc/nginx/nginx.conf(不同系统可能略有差异),整体结构示例如下:

nginx
# 全局配置块(main context)——影响整个 Nginx 实例
user  nginx nginx;
worker_processes  auto;
error_log  /var/log/nginx/error.log  warn;
pid  /run/nginx.pid;
 
include  /etc/nginx/modules-enabled/*.conf;
 
# 事件块(events context)——连接处理相关配置
events {
    worker_connections  1024;
    use                 epoll;
    multi_accept        on;
}
 
# HTTP 块(http context)——HTTP 协议相关配置
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
 
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 
    access_log  /var/log/nginx/access.log  main;
 
    # 服务器块(server context)——虚拟主机
    server {
        listen       80;
        server_name  example.com www.example.com;
 
        # 位置块(location context)——URI 匹配与处理
        location / {
            root   /var/www/html;
            index  index.html index.htm;
        }
 
        location /api/ {
            proxy_pass  http://backend_server;
        }
    }
}
 
# Stream 块(stream context)——TCP/UDP 四层代理
stream {
    upstream backend {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }
 
    server {
        listen      12345;
        proxy_pass  backend;
    }
}

常见上下文(Context)层级关系:

  • main:全局上下文,文件顶层,无大括号
  • events:连接处理
  • http:HTTP 服务配置
    • server:虚拟主机
      • location:URI 路径匹配与处理
      • ifmap 等子指令
  • stream:TCP/UDP(四层代理)
    • serverupstream
  • upstream:后端服务器组(可出现在 httpstream 中)

2. 核心语法规则总览

2.1 指令语法与参数

Nginx 配置由大量指令(directive)组成,每条指令的基本语法为:

nginx
directive_name  param1  param2  ...;

规范说明:

  • 每条指令必须以分号 ; 结尾
  • 指令名与参数之间使用一个或多个空格或 Tab 分隔
  • 可以有一个或多个参数,参数之间以空格分隔
  • 指令通常不区分大小写,但惯例使用小写

示例:

nginx
worker_processes  2;
access_log        /var/log/nginx/access.log;

错误示例(缺少分号):

nginx
worker_processes  2
error_log  /var/log/nginx/error.log

建议:编写或修改配置后,始终执行 nginx -t 进行语法检查。

2.2 上下文(Context)与继承

上下文可以理解为“指令的作用域”,用大括号 {} 包裹,且可以嵌套:

nginx
# 1. 全局上下文(main,顶级,无大括号)
worker_processes  auto;
 
# 2. 事件上下文
events {
    worker_connections  1024;
}
 
# 3. HTTP 上下文
http {
    # 4. server 上下文
    server {
        # 5. location 上下文
        location /path {
            proxy_pass  http://backend;
        }
    }
}
 
# 6. stream 上下文
stream {
    server {
        listen  3306;
    }
}

上下文继承规则:

  • 子上下文默认继承父上下文中可继承的指令值,如 http 中定义的 log_formatgzip 设置可被 serverlocation 继承
  • 子上下文可重写父上下文的配置,例如在某个 server 中覆盖 access_logclient_max_body_size
  • 部分指令只能出现在特定上下文中,写错位置会导致 nginx -t 报错,例如 worker_processes 只能在 mainlocation 不能出现在 events

2.3 include 模块化配置

include 用于拆分配置文件,提升可维护性:

nginx
include  /etc/nginx/mime.types;
include  /etc/nginx/conf.d/*.conf;
include  /etc/nginx/sites-enabled/*;

最佳实践:

  • 按功能拆分:gzip、security、ssl、proxy 等
  • 按业务拆分:每个虚拟主机一个 server 配置文件
  • 使用 sites-available + sites-enabled 软链接模式控制启用/禁用站点

2.4 变量(Variables)

变量以 $ 开头,在请求处理过程中可动态取值,是实现灵活路由与日志记录的重要机制。

常用内置变量示例:

nginx
$remote_addr      # 客户端 IP
$request_uri      # 含查询参数的完整 URI
$uri              # 去掉查询参数后的 URI
$status           # 响应状态码
$host             # 请求头 Host
$http_user_agent  # User-Agent
$scheme           # 协议(http / https)

在配置中使用变量示例:

nginx
location / {
    return 301  $scheme://www.example.com$request_uri;
}

自定义变量示例(配合 setif 等指令):

nginx
set  $is_mobile  0;
 
if ($http_user_agent ~* '(Android|iPhone)') {
    set  $is_mobile  1;
}

2.5 注释与可读性

Nginx 使用 # 进行单行注释,从 # 开始到行尾均为注释内容:

nginx
# 这是单行注释
user  nginx;
 
server {
    listen  80;     # 监听 80 端口
}

建议:在关键配置附近简要说明用途和修改原因,有助于多人协作与后期排查。


3. 核心上下文详解

3.1 全局上下文(main)

全局上下文位于配置文件顶层,无大括号,主要影响 Nginx 进程本身:

nginx
user              nginx nginx;
worker_processes  auto;
daemon            on;
pid               /run/nginx.pid;
 
error_log         /var/log/nginx/error.log  warn;
worker_rlimit_nofile  65535;

常用指令说明:

  • user:指定 worker 进程运行的用户和用户组
  • worker_processes:工作进程数,常设为 auto 或 CPU 核心数
  • daemon:是否以前台/守护进程模式运行
  • error_log:错误日志路径及日志级别(debug | info | notice | warn | error | crit
  • pid:保存 master 进程 PID 的文件路径
  • worker_rlimit_nofile:提升 worker 进程可打开的最大文件描述符数,需配合系统 ulimit 调整

3.2 events 上下文

events 与连接处理模型相关,对高并发性能影响较大:

nginx
events {
    use                 epoll;
    worker_connections  10240;
    multi_accept        on;
    accept_mutex        on;
    accept_mutex_delay  500ms;
}

关键指令:

  • use:事件驱动模型,Linux 下推荐 epoll
  • worker_connections:单个 worker 最多并发连接数(理论最大连接数约为 worker_processes * worker_connections
  • multi_accept:开启后一次 accept 尽可能多地接受新连接
  • accept_mutex:多个 worker 争抢新连接时的互斥机制,一般保持 on

3.3 http 上下文

http 是 Web 相关功能的“大容器”,包括日志、连接、缓存、压缩等:

nginx
http {
    include       mime.types;
    default_type  application/octet-stream;
    charset       utf-8;
 
    log_format  main '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent"';
 
    access_log  /var/log/nginx/access.log  main  buffer=32k  flush=5s;
 
    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    keepalive_timeout  65;
    keepalive_requests 100;
 
    client_max_body_size    10m;
    client_body_timeout     12;
    client_header_timeout   12;
 
    open_file_cache          max=1000 inactive=20s;
    open_file_cache_valid    30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors   on;
 
    gzip            on;
    gzip_min_length 1000;
    gzip_types      text/plain text/css application/json application/javascript;
 
    include  /etc/nginx/conf.d/*.conf;
    include  /etc/nginx/sites-enabled/*;
}

常用指令要点:

  • 日志相关
    • log_format:定义日志格式
    • access_log:访问日志路径、使用的格式、缓冲策略
  • 连接与传输
    • sendfile on:启用零拷贝,提升静态文件传输效率
    • tcp_nopushtcp_nodelay:配合 sendfile 调整包发送行为
    • keepalive_timeout:长连接保持时间
  • 客户端限制
    • client_max_body_size:限制上传体积
    • client_body_timeout / client_header_timeout:超时时间
  • 打开文件缓存
    • open_file_cache 系列:减少频繁的 stat 系统调用
  • 压缩
    • gzipgzip_types:配置内容压缩

3.4 server 上下文

server 用于定义虚拟主机,一个 Nginx 实例可以有多个 server

nginx
server {
    listen       80;
    listen       [::]:80;
    listen       443 ssl http2;
 
    server_name  example.com www.example.com;
 
    root   /var/www/example.com;
    index  index.html index.htm;
 
    ssl_certificate      /etc/ssl/certs/example.com.crt;
    ssl_certificate_key  /etc/ssl/private/example.com.key;
 
    error_page  404              /404.html;
    error_page  500 502 503 504  /50x.html;
 
    allow  192.168.1.0/24;
    deny   all;
 
    location / {
        try_files  $uri $uri/ /index.html;
    }
}

关键点:

  • listen:监听端口、协议(sslhttp2 等)
  • server_name:匹配域名,可支持通配符或正则
  • root / index:站点根目录与默认首页
  • error_page:自定义错误页面
  • allow / deny:基于 IP 的访问控制(更复杂场景建议配合 geomap

3.5 location 上下文

location 用于匹配 URI,并执行特定处理逻辑。

匹配优先级(从高到低):

  1. = 精确匹配
  2. ^~ 前缀匹配(匹配成功后不再进行正则匹配)
  3. ~ / ~* 正则匹配(区分/不区分大小写)
  4. 普通前缀匹配,如 location /(默认兜底)

示例:

nginx
location = /favicon.ico {
    access_log     off;
    log_not_found  off;
    expires        365d;
}
 
location ^~ /static/ {
    alias   /var/www/static/;
    expires 30d;
    add_header  Cache-Control  "public";
}
 
location ~ \.(php|php5|php7)$ {
    fastcgi_pass   unix:/var/run/php-fpm.sock;
    include        fastcgi_params;
}
 
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires     365d;
    add_header  Cache-Control  "public";
}
 
location / {
    try_files  $uri $uri/ /index.php?$query_string;
}

常用指令:

  • alias:与 root 不同,alias 替换整个路径前缀
  • try_files:按顺序尝试文件是否存在,不存在则回退到最后一个参数(可为 URI 或 404)

3.6 upstream / stream 上下文

upstream(HTTP / Stream 负载均衡)

nginx
upstream backend {
    least_conn;
 
    server  backend1.example.com:8080  weight=3;
    server  backend2.example.com:8080;
    server  backend3.example.com:8080  backup;
    server  backend4.example.com:8080  down;
}
 
server {
    listen  80;
 
    location /api/ {
        proxy_pass  http://backend;
    }
}

说明:

  • 负载均衡算法:默认轮询(round-robin),可显式使用 least_conn(最少连接)或第三方模块扩展
  • weight:权重
  • backup:备份服务器
  • down:标记为不参与负载

提示:示例中的主动健康检查指令如 health_check 并非开源版 Nginx 的标准指令,通常来自商业版或第三方模块,使用时需确认模块支持。

stream(TCP/UDP 四层代理)

nginx
stream {
    upstream mysql_backend {
        server  10.0.0.10:3306;
        server  10.0.0.11:3306;
    }
 
    server {
        listen      3306;
        proxy_pass  mysql_backend;
    }
}

4. 高级语法特性

4.1 if 条件判断(慎用)

if 是 Nginx 中最容易被误用的指令之一,错误使用可能导致逻辑混乱甚至意外的 500 错误。推荐优先使用 map、独立 location 等方式替代。

示例(仅用于说明语法):

nginx
location / {
    if ($request_method = POST) {
        return 405;
    }
 
    if ($http_user_agent ~* '(Android|iPhone)') {
        set  $is_mobile  1;
    }
 
    if ($is_mobile = 1) {
        root  /var/www/mobile;
    }
}

经验建议:

  • 避免在 location 内嵌套复杂多层 if
  • 避免通过 if 修改 proxy_pass 等关键指令,优先用 map 到变量再使用

4.2 map 映射变量

maphttp 上下文中使用,用于将一个变量映射到另一个变量,适合处理复杂的分支逻辑:

nginx
map $http_user_agent $is_bad_bot {
    default                      0;
    ~*(bot|crawler|spider)       1;
    ~*(baidu|google|bing)        0;
}
 
server {
    if ($is_bad_bot) {
        return 403;
    }
}

适用场景:

  • 按 UA、IP、Host 切分流量
  • 按业务规则设定后端集群、日志级别等

4.3 limit_except 限制 HTTP 方法

location 中使用 limit_except 指定允许的 HTTP 方法,其余方法将按照内部配置拒绝:

nginx
location /api/ {
    limit_except GET POST {
        deny  all;
    }
}

适合场景:

  • 对只读接口限制为 GET
  • 对管理接口限制访问方法并结合 IP 白名单

4.4 geo 基于 IP 的变量

geo 可根据客户端 IP 赋予变量不同的值:

nginx
geo $client_region {
    default          unknown;
    192.168.1.0/24   office;
    10.0.0.0/8       internal;
 
    include          /etc/nginx/geo.conf;
}

常用用途:

  • 按地区分流(不同机房/国家)
  • 按来源 IP 进行黑白名单控制

5. 配置文件组织与工程化实践

典型目录结构推荐如下:

text
/etc/nginx/
├── nginx.conf              # 主配置文件(main + events + http 引用)
├── mime.types              # MIME 类型映射
├── fastcgi_params
├── uwsgi_params
├── scgi_params
├── proxy_params

├── conf.d/                 # 通用配置片段(全局生效)
│   ├── gzip.conf
│   ├── security.conf
│   └── ssl.conf

├── sites-available/        # 可用虚拟主机
│   ├── example.com.conf
│   └── app.example.com.conf

├── sites-enabled/          # 启用虚拟主机(符号链接)
│   ├── example.com.conf -> ../sites-available/example.com.conf
│   └── app.example.com.conf -> ../sites-available/app.example.com.conf

└── snippets/               # 可复用片段
    ├── security-headers.conf
    ├── cors.conf
    └── rate-limiting.conf

工程化建议:

  • 将通用安全、gzip、缓存等配置提炼为 snippetsconf.d 片段
  • 站点级配置统一放在 sites-available,通过软链接控制启用
  • 对生产环境与测试环境使用独立配置目录或独立主配置文件

6. 配置测试、调试与排错

6.1 测试配置语法

bash
# 测试默认配置文件
nginx -t
 
# 指定配置文件路径
nginx -t -c /etc/nginx/nginx.conf

输出包含:

  • syntax is ok:语法无误
  • test is successful:文件引用等检查通过

6.2 平滑重载与日志

bash
# 平滑重载(不中断现有连接)
nginx -s reload
 
# 重新打开日志文件(配合日志轮转)
nginx -s reopen

开启调试日志:

nginx
error_log  /var/log/nginx/error.log  debug;

6.3 简单调试 Location

通过自定义响应头快速查看变量值:

nginx
location /debug {
    add_header  X-Debug-Remote-Addr  $remote_addr;
    add_header  X-Debug-Host         $host;
    add_header  X-Debug-Uri          $request_uri;
    return 200 "OK";
}

7. 性能优化相关配置建议

以下为常见的性能优化方向,需结合业务实际压测验证:

  • 进程与连接数
    • worker_processes auto:让 Nginx 自动根据 CPU 核数选择 worker 数
    • worker_connections:根据峰值连接数与内核 FD 限制调整
  • 文件描述符
    • 提高系统 ulimit -nworker_rlimit_nofile
  • 网络层优化
    • 在 Linux 内核中调整 somaxconntcp_max_syn_backlog 等参数
  • 静态资源优化
    • 使用 sendfile on、长 expires、合理的 Cache-Control
  • 压缩与缓存
    • 针对文本类资源启用 gzipbrotli(如有模块)
    • 配置 proxy_cachefastcgi_cache 缓存动态内容
  • 日志与 IO
    • 为高并发接口调整 access_log 缓冲大小或按需关闭

8. 安全配置与访问控制

常见安全配置方向:

  • 基础安全 header

    将以下内容抽取为 snippets/security-headers.conf 复用:

    nginx
    add_header  X-Frame-Options        SAMEORIGIN;
    add_header  X-Content-Type-Options nosniff;
    add_header  X-XSS-Protection       "1; mode=block";
  • 隐藏版本信息

    nginx
    http {
        server_tokens  off;
    }
  • 限制请求大小与速率

    • client_max_body_size:限制上传大小
    • 使用 limit_req_zonelimit_req 实现基础限流(可抽成片段)
  • 访问控制

    在敏感接口或管理后台结合 IP 白名单:

    nginx
    location /admin {
        allow  192.168.1.0/24;
        deny   all;
    }
  • HTTPS 配置

    • 使用现代 TLS 配置和安全的 cipher 列表
    • 强制 HTTP 重定向到 HTTPS

9. 常见错误与 FAQ

9.1 常见错误类型

  1. 缺少分号
    • 现象:nginx -t 提示语法错误,多出现在上一行末尾
  2. 上下文错误
    • 现象:指令放在不支持的上下文,报 “directive is not allowed here”
  3. 路径错误
    • 相对路径往往相对于编译时 --prefix 或运行时 root 指定目录
  4. 权限问题
    • Nginx 进程对证书、站点目录、日志目录无读写权限
  5. 端口冲突
    • listen 的端口已被其他进程占用

9.2 FAQ 示例

  • Q:修改完配置后应该怎样上线?
    A:先执行 nginx -t 确认配置无误,再执行 nginx -s reload 平滑重载。

  • Q:如何定位某个请求匹配到了哪个 location
    A:可以临时在候选 location 中加上不同的 add_header 标记或特定响应体,通过实际访问来验证匹配结果。

  • Q:多个 serverserver_name 相同会怎样?
    A:通常按配置顺序匹配到第一个,除非显式配置 default_server,因此应避免冲突或混淆。

掌握 Nginx 配置语法与常用模式后,可以从简单场景入手,逐步引入反向代理、缓存、限流、安全等高级特性,并在每次调整后使用 nginx -t 与压测工具验证行为与性能。